/*
 * VectorBuilder.cs
 * 
 * Copyright (c) 2005-2006, dnAnalytics. All rights reserved.
*/
using System;
using dnAnalytics.LinearAlgebra.Native;

namespace dnAnalytics.LinearAlgebra
{
    /// <summary>
    /// A static class used to create <see cref="Vector"/> objects.
    /// </summary>
    public static class VectorBuilder
    {
        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size. All elements are initialized to zero.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <returns>A <see cref="Vector"/> of the requested size.</returns>
        /// <remarks><see cref="Settings.DefaultVectorType"/> determines the storage type to use.
        /// Uses <see cref="Settings.UseNativeLibrary"/> to determine whether to use native BLAS routines or not. If
        /// native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size)
        {
            return CreateVector(size, Settings.DefaultVectorType, Settings.UseNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size. All elements are initialized to zero.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <param name="vectorType">The type of vector to create.</param>
        /// <returns>A <see cref="Vector"/> of the requested size.</returns>
        /// <remarks> Uses <see cref="Settings.UseNativeLibrary"/> to determine whether to use native BLAS routines or not. If
        /// native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size, VectorType vectorType)
        {
            return CreateVector(size, vectorType, Settings.UseNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size. All elements are initialized to zero.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <param name="useNativeLibrary">Whether to use native BLAS routines or not.</param>
        /// <returns>A <see cref="Vector"/> of the requested size.</returns>
        /// <remarks><see cref="Settings.DefaultVectorType"/> determines the storage type to use.
        /// If native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size, bool useNativeLibrary)
        {
            return CreateVector(size, Settings.DefaultVectorType, useNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size. All elements are initialized to zero.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <param name="vectorType">The type of vector to create.</param>
        /// <param name="useNativeLibrary">Whether to use native BLAS routines or not.</param>
        /// <returns>A <see cref="Vector"/> of the requested size.</returns>
        /// <remarks>If native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size, VectorType vectorType, bool useNativeLibrary)
        {
            if (size < 1)
            {
                throw new ArgumentException("size", dnAnalytics.Resources.Strings.NotPositiveException);
            }

            Vector ret = null;
            switch (vectorType)
            {
                case VectorType.Dense:
                    ret = new DenseVector(size, useNativeLibrary);
                    break;
                case VectorType.Sparse:
                    ret = new SparseVector(size);
                    break;
            }
            return ret;
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size and sets its elements to the given value.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <param name="value">The value to set all elements to.</param>
        /// <returns>A <see cref="Vector"/> with the given size and all elements set to the given value.</returns>
        /// <remarks><see cref="Settings.DefaultVectorType"/> determines the storage type to use.
        /// Uses <see cref="Settings.UseNativeLibrary"/> to determine whether to use native BLAS routines or not. If
        /// native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size, double value)
        {
            return CreateVector(size, value, Settings.UseNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size and sets its elements to the given value.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <param name="value">The value to set all elements to.</param>
        /// <param name="vectorType">The type of vector to create.</param>
        /// <returns>A <see cref="Vector"/> with the given size and all elements set to the given value.</returns>
        /// <remarks>Uses <see cref="Settings.UseNativeLibrary"/> to determine whether to use native BLAS routines or not. If
        /// native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size, double value, VectorType vectorType)
        {
            return CreateVector(size, value, vectorType, Settings.UseNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size and sets its elements to the given value.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <param name="value">The value to set all elements to.</param>
        /// <param name="useNativeLibrary">Whether to use native a native BLAS library or not.</param>
        /// <returns>A <see cref="Vector"/> with the given size and all elements set to the given value.</returns>
        /// <remarks><see cref="Settings.DefaultVectorType"/> determines the storage type to use.
        /// If native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size, double value, bool useNativeLibrary)
        {
            return CreateVector(size, value, Settings.DefaultVectorType, useNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the given size and sets its elements to the given value.
        /// </summary>
        /// <param name="size">The size of the <see cref="Vector"/> to create.</param>
        /// <param name="value">The value to set all elements to.</param>
        /// <param name="vectorType">The type of vector to create.</param>
        /// <param name="useNativeLibrary">Whether to use native a native BLAS library or not.</param>
        /// <returns>A <see cref="Vector"/> with the given size and all elements set to the given value.</returns>
        /// <remarks>If native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentException">If <paramref name="size"/> is not positive.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(int size, double value, VectorType vectorType, bool useNativeLibrary)
        {
            if (size < 1)
            {
                throw new ArgumentException("size", dnAnalytics.Resources.Strings.NotPositiveException);
            }

            Vector ret = null;
            switch (vectorType)
            {
                case VectorType.Dense:
                    ret = new DenseVector(size, value, useNativeLibrary);
                    break;
                case VectorType.Sparse:
                    double[] values = new double[size];
                    for (int i = 0; i < values.Length; i++)
                    {
                        values[i] = value;
                    }
                    ret = new SparseVector(values);
                    break;
            }
            return ret;
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the same size and values of the given array.
        /// </summary>
        /// <param name="values">The array to copy data from.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <returns>A <see cref="Vector"/> with the same size and values of the given array.</returns>
        /// <remarks><see cref="Settings.DefaultVectorType"/> determines the storage type to use.
        /// Uses <see cref="Settings.UseNativeLibrary"/> to determine whether to use native BLAS routines or not. If
        /// native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(double[] values)
        {
            return CreateVector(values, Settings.DefaultVectorType, Settings.UseNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the same size and values of the given array.
        /// </summary>
        /// <param name="values">The array to copy data from.</param>
        /// <param name="vectorType">The type of vector to create.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <returns>A <see cref="Vector"/> with the same size and values of the given array.</returns>
        /// <remarks>Uses <see cref="Settings.UseNativeLibrary"/> to determine whether to use native BLAS routines or not. If
        /// native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(double[] values, VectorType vectorType)
        {
            return CreateVector(values, vectorType, Settings.UseNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the same size and values of the given array.
        /// </summary>
        /// <param name="values">The array to copy data from.</param>
        /// <param name="useNativeLibrary">Whether to use native a native BLAS library or not.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <returns>A <see cref="Vector"/> with the same size and values of the given array.</returns>
        /// <remarks><see cref="Settings.DefaultVectorType"/> determines the storage type to use.
        /// If native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(double[] values, bool useNativeLibrary)
        {
            return CreateVector(values, Settings.DefaultVectorType, useNativeLibrary);
        }

        /// <summary>
        /// Creates a <see cref="Vector"/> with the same size and values of the given array.
        /// </summary>
        /// <param name="values">The array to copy data from.</param>
        /// <param name="vectorType">The type of vector to create.</param>
        /// <param name="useNativeLibrary">Whether to use native a native BLAS library or not.</param>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <returns>A <see cref="Vector"/> with the same size and values of the given array.</returns>
        /// <remarks>If native BLAS routines are used, <see cref="Settings.Blas"/> sets which <see cref="BlasProvider"/> to use.</remarks>
        /// <exception cref="ArgumentNullException">If <paramref name="values"/> is <b>null</b>.</exception>
        /// <seealso cref="Settings"/>
        /// <seealso cref="BlasProvider"/>
        public static Vector CreateVector(double[] values, VectorType vectorType, bool useNativeLibrary)
        {
            if (values == null)
            {
                throw new ArgumentNullException("values", dnAnalytics.Resources.Strings.NullParameterException);
            }

            Vector ret = null;
            switch (vectorType)
            {
                case VectorType.Dense:
                    ret = new DenseVector(values, useNativeLibrary);
                    break;
                case VectorType.Sparse:
                    ret = new SparseVector(values);
                    break;
            }
            return ret;
        }
    }
}
